using System;
using System.Xml;
using System.Data;
using System.Collections;
using System.Runtime.Remoting;

using System.ComponentModel;
using System.Runtime.Remoting.Lifetime;

namespace Model
{
	/// <summary>
	/// Summary description for DatabaseManagerADO.
	/// </summary>
	public class DatabaseManagerADO :MarshalByRefObject, IRemoteService
	{
		private DatabaseStorage myDatabaseStorage;
		private Hashtable OnlineUser;
		private DataSet mizDB;
		private string fileName;
		private string schemaFileName = "MizaniyaDB.xsd" ;

		#region declaration of tables
		private DataTable userTable;
		private DataTable accountTable;
		private DataTable consumerTable;
		private DataTable payeeTable;
		private DataTable notificationsTable;
		private DataTable transactionTable;
		#endregion

		#region declaration of relations
		private DataRelation relUsersAccount;
		private DataRelation relUserConsumer;
		private DataRelation relUserPayee;
		private DataRelation relUserNotifications;
		private DataRelation relUserTransactionCreator;
		private DataRelation relUserTransactionMod;
		private DataRelation relAccountConsumer; 
		private DataRelation relAccountPayee; 
		private DataRelation relTransactionConsumer; 
		private DataRelation relTransactionPayee; 
		private DataRelation relTransactionNotifications; 
		#endregion

		public DatabaseManagerADO(string FileName, string schemaFileName)
		{
			fileName = FileName;
			this.schemaFileName=schemaFileName;
			//myDatabaseStorage= new DatabaseStorage(FileName);
			mizDB = new DataSet();

			// read off the schema
			mizDB.ReadXmlSchema(schemaFileName);
			

			#region initilization of tables
			// user table
			userTable = mizDB.Tables["User"];

			// account table
			accountTable = mizDB.Tables["Account"];
			accountTable.Columns["ID"].AutoIncrement=true;
			accountTable.Columns["ID"].AutoIncrementSeed=0;
			accountTable.Columns["ID"].AutoIncrementStep=1;

			// payees table
			payeeTable = mizDB.Tables["Payee"];
			payeeTable.Columns["ID"].AutoIncrement=true;
			payeeTable.Columns["ID"].AutoIncrementSeed=0;
			payeeTable.Columns["ID"].AutoIncrementStep=1;

			// consumers table
			consumerTable = mizDB.Tables["Consumer"];
			consumerTable.Columns["ID"].AutoIncrement=true;
			consumerTable.Columns["ID"].AutoIncrementSeed=0;
			consumerTable.Columns["ID"].AutoIncrementStep=1;

			// notifications
			notificationsTable = mizDB.Tables["Notifications"];
			notificationsTable.Columns["ID"].AutoIncrement=true;
			notificationsTable.Columns["ID"].AutoIncrementSeed=0;
			notificationsTable.Columns["ID"].AutoIncrementStep=1;

			//transaction
			transactionTable = mizDB.Tables["Transaction"];
			transactionTable.Columns["ID"].AutoIncrement=true;
			transactionTable.Columns["ID"].AutoIncrementSeed=0;
			transactionTable.Columns["ID"].AutoIncrementStep=1;
			#endregion


			#region initialization of relations
			relUsersAccount = new DataRelation("relUsersAccount",
				mizDB.Tables["User"].Columns["Name"],
				mizDB.Tables["Account"].Columns["OwnerName"]);
			mizDB.Relations.Add(relUsersAccount);

			relUserPayee = new DataRelation("relUserPayee",
				userTable.Columns["Name"],
				payeeTable.Columns["UserID"]);
			mizDB.Relations.Add(relUserPayee);
				
			relUserNotifications = new DataRelation("relUserNotifications",
				userTable.Columns["Name"],
				notificationsTable.Columns["UserID"]);
			mizDB.Relations.Add(relUserNotifications);

			relUserConsumer = new DataRelation("relUserConsumer",
				userTable.Columns["Name"],
				consumerTable.Columns["UserID"]);
			mizDB.Relations.Add(relUserConsumer);	

			relTransactionNotifications = new DataRelation("relTransactionNotifications",
				transactionTable.Columns["ID"],
				notificationsTable.Columns["TransactionID"]);
			mizDB.Relations.Add(relTransactionNotifications);            

			relUserTransactionCreator= new DataRelation("relUserTransactionCreator",
				userTable.Columns["Name"],
				transactionTable.Columns["Creator"]);
			mizDB.Relations.Add(relUserTransactionCreator);

			relUserTransactionMod= new DataRelation("relUserTransactionMod",
				userTable.Columns["Name"],
				transactionTable.Columns["LastModifiedBy"]);
			mizDB.Relations.Add(relUserTransactionMod);

			relAccountConsumer = new DataRelation("relAccountConsumer",
				accountTable.Columns["ID"],
				consumerTable.Columns["AccountID"]);
			mizDB.Relations.Add(relAccountConsumer);

			relAccountPayee = new DataRelation("relAccountPayee",
				accountTable.Columns["ID"],
				payeeTable.Columns["AccountID"]);
			mizDB.Relations.Add(relAccountPayee);

			relTransactionPayee = new DataRelation("relTransactionPayee",
				transactionTable.Columns["ID"],
				payeeTable.Columns["TransactionID"]);
			mizDB.Relations.Add(relTransactionPayee);

			relTransactionConsumer = new DataRelation("relTransactionConsumer",
				transactionTable.Columns["ID"],
				consumerTable.Columns["TransactionID"]);
			mizDB.Relations.Add(relTransactionConsumer);
			#endregion
		

			// read the data from the xml file
			try
			{
				mizDB.ReadXml(fileName);
			} 
			catch (Exception e) // the file does not exist/security permission
			{// create a new database
				updateXML();                
			}
		}

		

		/// <summary>
		/// THis method should return the usernames of all users registered in the database
		/// </summary>
		/// <returns>ArrayList of Strings</returns>
		public  ArrayList GetUserNames()
		{
			DataRow[] drUser;
			drUser = userTable.Select();
			ArrayList result=new ArrayList();

			foreach (DataRow iRD in drUser)
			{
				result.Add(iRD["Name"].ToString());
			}
			
			return result;			  

		}
		
		
		/// <summary>
		/// To validate user login 
		/// </summary>
		public bool ValidateLogin(UserIdentity user)
		{
			DataRow[] usersRow;
			usersRow = userTable.Select("Name = '"+user.Name+"'");

			foreach (DataRow iDataRow in usersRow)
			{
				if (iDataRow["Password"].Equals(user.Password))
				{
					
					return true;
				}
			}

			// if we reach here then either the password was wrong or the user was not found
			return false;

		}

		/// <summary>
		/// Add a new user to the System
		/// It also updates the DB
		/// </summary>
		public void AddNewUser(UserIdentity user)
		{
			if (userTable.Select("Name = '"+user.Name+"'").Length != 0)	// if the user already exists
			{
				throw new MizExceptions.UserAlreadyExistsException();
			}

			if (user.Name == "")
			{
				throw new MizExceptions.InvalidUserCredentialsException();
			}

			DataRow newUserRow = userTable.NewRow();
			makeRowFromUserIdentity(newUserRow,user);
			userTable.Rows.Add(newUserRow);

			updateXML();
		}

		/// <summary>
		/// If the user is logged in, the user's credentials are changed
		/// </summary>
		public void ChangePassword(UserIdentity user)
		{
			if (!isUserLogged(user)) new MizExceptions.UserNotLoggedInException();
			

			DataRow[] drsUser;
			drsUser = userTable.Select("Name = '"+user.Name+"'");
			ArrayList result=new ArrayList();

			for (int i=0;i<drsUser.Length;i++)	// note: we expect only one result
			{
				// update the record
				DataRow newUser = drsUser[i];
				newUser["Password"]=user.Password;
				drsUser[i]=newUser;
			}
			
			updateXML();	  
		}		

		/// <summary>
		/// Removes the user from the pool of logged on users
		/// </summary>
		public void LogOut(UserIdentity user)
		{
			// TODO: stub
			
		}

		/// <summary>
		/// Add new transaction into XML database
		/// </summary>
		public uint AddNewTransaction(UserIdentity user, Transaction transaction,ExternalAccount account)
		{
			//declare rows
			DataRow newTxRow = transactionTable.NewRow();
			
			


			//initialize rows
			makeRowFromTransaction(newTxRow,transaction);
			transaction.TransactionID=UInt32.Parse(newTxRow["ID"].ToString());	// initialize the transaction ID. needed for payee and consumer

			DataRow[] newPayeesRow = makePayeesRowFromTransaction( transaction,user.Name);
			DataRow[] newConsumersRow= makeConsumersRowFromTransaction(transaction);

			// add rows
			transactionTable.Rows.Add(newTxRow);
			foreach (DataRow iDR in newConsumersRow)
			{
				consumerTable.Rows.Add(iDR);
			}

			foreach (DataRow iDR in newPayeesRow)
			{
				payeeTable.Rows.Add(iDR);
			}

			updateXML();

			return UInt32.Parse(newTxRow["ID"].ToString());
		}

		/// <summary>
		/// Fetch all transactions in which a particular user is involved
		/// </summary>
		/// <param name="user"></param>
		/// <returns></returns>
		public ArrayList GetAllUserTransactions(UserIdentity user)
		{
			// go through all transactions and find those in which the user is either payee or consumer
			ArrayList result = new ArrayList();

			//find all transactions
			DataRow[] allTx = transactionTable.Select();
			foreach (DataRow drTx in allTx)
			{
				DataRow[] drsPayee = payeeTable.Select("UserID = '"+user.Name+"' AND TransactionID = '"+drTx["ID"]+"'");
				DataRow[] drsConsumer = consumerTable.Select("UserID = '"+user.Name+"' AND TransactionID = '"+drTx["ID"]+"'");

				if (drsConsumer.Length!=0 || drsPayee.Length!=0)	//if the current transaction involves the user
				{	// add the transaction to result
					Transaction foundTx = makeTransactionFromRow(drTx,user.Name);
					result.Add(foundTx);
				}
			}

			return result;
		}

		/// <summary>
		/// Fetch all transactions with a notification flag, in which a particular user is involved
		/// </summary>
		/// <param name="user"></param>
		/// <returns>ArrayList of transactions objects</returns>
		public ArrayList GetTransactionsWithNotifications(UserIdentity user)
		{
			ArrayList result = new ArrayList();
			ArrayList notificationsList = GetNotifications(user);	// get all the transaction id's

			// for each id, get the transaction object and add it to the list
			foreach ( string iNotification in notificationsList)
			{
				DataRow[] drTransaction;
				drTransaction = transactionTable.Select("ID = '"+iNotification+"'");
				foreach (DataRow iTransaction in drTransaction) //expect only one
				{
					result.Add(makeTransactionFromRow(iTransaction,user.Name));
				}
			}
			return result;

		}

		/// <summary>
		/// get the transaction id's of all transactions where the user is involved.
		/// </summary>
		/// <param name="user"></param>
		/// <returns>ArrayList of uints which are transaction id's</returns>
		public ArrayList GetNotifications(UserIdentity user)
		{
			ArrayList result = new ArrayList();
			DataRow[] drsUsers=	userTable.Select("Name = '"+user.Name+"'");

			

			foreach (DataRow iUser in drsUsers)	// expect only one
			{
				
				DataRow[] drsNotifications;
				drsNotifications = iUser.GetChildRows("relUserNotifications");

				foreach (DataRow iNotifications in drsNotifications)	// for each notification , return the corresponding transaction
				{
					result.Add(UInt32.Parse(iNotifications["TransactionID"].ToString()));
				}
			}

			return result;		
		}



		/// <summary>
		/// Update a transaction. (Does not send notifications.)
		/// </summary>
		/// <param name="user"></param>
		/// <param name="tx"></param>
		/// <param name="oldtx"></param>
		public void UpdateTransaction(UserIdentity user, Transaction tx,Transaction oldtx)
		{
			
			if (!isUserLogged(user)) new MizExceptions.UserNotLoggedInException();
			

			DataRow[] drsTx;
			drsTx = transactionTable.Select("ID = '"+oldtx.TransactionID+"'");

			for (int i=0;i<drsTx.Length;i++)	// note: we expect only one result
			{
				// update the transaction record
				DataRow drNewTx = drsTx[i];
				makeRowFromTransaction(drNewTx,tx);
				drsTx[i]=drNewTx;

				// remove all the consumer and payee's and add the new ones
				// TODO: the new payee rows dont have the correct ext account id's for other users. Reuse the old account id's for other users only.

				// find old payees
				DataRow[] drsPayee = payeeTable.Select("TransactionID ='"+oldtx.TransactionID+"'");
                
				// make new payess
				DataRow[] drsNewPayee = makePayeesRowFromTransaction(tx,user.Name);

				// the new payee rows dont have the correct ext account id's for other users. Reuse the old account id's for other users only.
				foreach (DataRow iDR in drsNewPayee)	// for each new payee
				{					
					foreach (DataRow iOldDR in drsPayee)	// check if the payee exists
					{
						if (iDR["UserID"].Equals(iOldDR["UserID"]) && !iDR["UserID"].Equals(user.Name))	// if the payee existed, and is not the current payee
						{// reuse old external account
							iDR["AccountID"]=iOldDR["AccountID"];
						}
					}					
				}

				// delete the old payees
				foreach (DataRow iOldDR in drsPayee)
				{
					iOldDR.Delete();
				}

				// add the new payees
				foreach (DataRow iDR in drsNewPayee)
				{
					payeeTable.Rows.Add(iDR);
				}	

				// delete consumers
				DataRow[] drsConsumer = consumerTable.Select("TransactionID ='"+oldtx.TransactionID+"'");
				foreach (DataRow iRow in drsConsumer)	
				{
					iRow.Delete();
				}

				// add consumers
				DataRow[] drsNewConsumer = makeConsumersRowFromTransaction(tx);
				foreach (DataRow iDR in drsNewConsumer)
				{
					consumerTable.Rows.Add(iDR);
				}

			}
			
			updateXML();
		}

		
		public void AddNewExternalAccount(UserIdentity user, ExternalAccount account)
		{
			DataRow newAccountRow = accountTable.NewRow();
			makeRowFromExternalAccount(newAccountRow,account);

			accountTable.Rows.Add(newAccountRow);

			updateXML();

            		
		}

		/// <summary>
		/// Fetch all external account information of a user
		/// </summary>
		/// <returns>an arraylist of ExternalAccounts</returns>
		public  ArrayList GetAllUserExternalAccounts(UserIdentity user)
		{
			DataRow[] dtUsers;
			ArrayList result = new ArrayList();
			dtUsers= userTable.Select("Name = '"+user.Name+"'");

			DataRow[] drAccount = dtUsers[0].GetChildRows("relUsersAccount");

			foreach (DataRow iDR in drAccount)
			{
				ExternalAccount extAcc = makeExternalAccountFromRow(iDR);
				result.Add(extAcc);
			}

			return result;

		}

		/// <summary>
		/// Remove the notification for this user on this transaction id
		/// </summary>
		/// <param name="transactionID"></param>
		public void TransactionNotificationApproved(UserIdentity user, uint transactionID)
		{
			if (!isUserLogged(user)) throw new MizExceptions.UserNotLoggedInException();

			DataRow[] drNn;
			drNn =  notificationsTable.Select("TransactionID = '"+transactionID+"' AND UserID = '"+user.Name+"'");
			
			foreach (DataRow iRow in drNn)	// expect only 1
			{
				iRow.Delete();
			}

			notificationsTable.AcceptChanges();
			updateXML();

		}

		public void DeleteTransaction(UserIdentity user,uint ID)
		{
				
			if (!isUserLogged(user)) new MizExceptions.UserNotLoggedInException();
			

			DataRow[] drsTx;
			drsTx = transactionTable.Select("ID = '"+ID+"'");

			foreach (DataRow drTxToDel in drsTx)
			{
				drTxToDel.Delete();

				// delete payees
				DataRow[] drsPayee = payeeTable.Select("TransactionID ='"+ID+"'");
				foreach (DataRow iRow in drsPayee)	// expect only 1
				{
					iRow.Delete();
				}

				// delete consumers
				DataRow[] drsConsumer = consumerTable.Select("TransactionID ='"+ID+"'");
				foreach (DataRow iRow in drsConsumer)	// expect only 1
				{
					iRow.Delete();
				}

			}
			
			updateXML();
		}
		
		/// <summary>
		/// Add a notification to the user's notification list
		/// </summary>
		/// <param name="user"></param>
		/// <param name="TransactionID"></param>
		/// <param name="UserName"></param>
		public void NotifyUserOnTransaction(UserIdentity user, String userName, uint TransactionID)
		{
			DataRow notify=notificationsTable.NewRow();

			notify["UserID"]=userName;
			notify["TransactionID"]=TransactionID;

			notificationsTable.Rows.Add(notify);		
	
		}
		
		/// <summary>
		/// will notify list of users of a trasaction
		/// </summary>
		/// <param name="user"></param>
		/// <param name="TransactionID"></param>
		/// <param name="usersToNotify"></param>
		public void NotifyUsersOnTransaction(UserIdentity user, uint transactionID, string[] usersToNotify)
		{
			if (!isUserLogged(user)) throw new MizExceptions.UserNotLoggedInException();

			foreach (string  iUser in usersToNotify)
			{
				NotifyUserOnTransaction(user, iUser,transactionID);
			}
		}


		public void UpdateExternalAccount(UserIdentity user, ExternalAccount oldAcc,ExternalAccount newAcc)
		{
			if (!isUserLogged(user)) new MizExceptions.UserNotLoggedInException();

			DataRow[] drsOldAccount = accountTable.Select("OwnerName = '"+user.Name+"' AND AccountName = '"+oldAcc.AccountName+"'");

			for (int i =0;i<drsOldAccount.Length;i++)	// expect only 1
			{
                DataRow newRow = drsOldAccount[i];
				makeRowFromExternalAccount(newRow,newAcc);
				drsOldAccount[i]=newRow;
			}

			updateXML();

		}

		private void makeRowFromUserIdentity(DataRow userRow, UserIdentity user)
		{
			userRow["Name"] = user.Name;
			userRow["Password"] = user.Password;
		}

		private void makeRowFromExternalAccount(DataRow accountRow, ExternalAccount account)
		{
			accountRow["AccountName"]=account.AccountName;
			accountRow["Balance"]=account.Balance;
			accountRow["OwnerName"]=account.OwnerName;

			if (account is CreditCard)
			{
				CreditCard accountCC = (CreditCard)account;
				accountRow["CreditLimit"]=	accountCC.CreditLimit;
				accountRow["Type"]="CreditCard";
			}

			else if (account is BankAccount)
			{
				BankAccount accountBA = (BankAccount) account;
				accountRow["Website"]=accountBA.Website;
				accountRow["Type"]="BankAccount";
			}
			else
			{
				accountRow["Type"]="Cash";
			}
			
		}

		private ExternalAccount makeExternalAccountFromRow(DataRow accountRow)
		{
			
			string userName = accountRow.GetParentRow("relUsersAccount")["Name"].ToString();
			decimal balance = Decimal.Parse(accountRow["Balance"].ToString());
			string accName = accountRow["AccountName"].ToString();
			ExternalAccount result=null;

			switch (accountRow["Type"].ToString())
			{
				case "Cash":
                    // TODO: This is prolly supposed to be an instance of Cash
					result = new ExternalAccount(accName,userName,balance);
					break;
				case "CreditCard":
					decimal cLimit= Decimal.Parse(accountRow["CreditLimit"].ToString());
					result = new CreditCard(accName,userName,cLimit);
					result.Balance=Decimal.Parse(accountRow["Balance"].ToString());
					break;
				case "BankAccount":
					string web =accountRow["Website"].ToString();				
					result = new BankAccount(accName,userName,web);
					result.Balance=Decimal.Parse(accountRow["Balance"].ToString());
					break;
			}
			
			return result;
		}

		~DatabaseManagerADO()
		{
			//updateXML();
		}

		private void updateXML()
		{
			mizDB.WriteXml(this.fileName,System.Data.XmlWriteMode.IgnoreSchema);
		}

		private void makeRowFromTransaction(DataRow newTxRow,Transaction tx)
		{
			newTxRow["Date"]=tx.Date.ToString();
			newTxRow["TransactionType"]=tx.Type;
			newTxRow["LastModifiedBy"]=tx.LastModifiedBy;
			newTxRow["Description"] = tx.CategoryDescription;
			newTxRow["Creator"] = tx.Creator;
			newTxRow["Subject"]= tx.Subject;			
		}

		private DataRow[] makePayeesRowFromTransaction(Transaction tx, string currUserName)
		{
			ArrayList payeeListRow = new ArrayList();
			foreach (UserAmountPair iPayee in tx.InvolvedPayees)
			{
				DataRow idr=payeeTable.NewRow();
				idr["UserID"]=iPayee.username;
				idr["Amount"]=iPayee.amount;
				idr["TransactionID"]=tx.TransactionID;


				// find the account to use for this payee
				string accountName;
				if (iPayee.username.Equals(currUserName))	// if it is the logged in user, use the account specified
				{
					accountName=tx.SourceExternalAccount;

					DataRow[] userInvolvedAccount = accountTable.Select("(OwnerName = '" +iPayee.username+"') AND (AccountName = '"+accountName+"')");
					idr["AccountID"] = userInvolvedAccount[0]["ID"];	// we expect only one account with this name
				}
				else	// use no account by default
				{
					idr["AccountID"] = -1;
				}			
	
				
				payeeListRow.Add(idr);
			}

			return  (DataRow[])payeeListRow.ToArray(typeof(System.Data.DataRow));

		}

		private DataRow[] makeConsumersRowFromTransaction(Transaction tx)
		{
			ArrayList consumerListRow = new ArrayList();
			foreach (UserAmountPair iConsumer in tx.InvolvedConsumers)
			{
				DataRow idr=consumerTable.NewRow();
				idr["UserID"]=iConsumer.username;
				idr["Amount"]=iConsumer.amount;
				idr["TransactionID"]=tx.TransactionID;

                consumerListRow.Add(idr);
			}

			return (DataRow[])consumerListRow.ToArray(typeof(System.Data.DataRow));

		}

		private Transaction makeTransactionFromRow(DataRow tx, string currUserName)
		{
			Transaction result = new Transaction();
			result.CategoryDescription = tx["Description"].ToString();
			result.Creator = tx["Creator"].ToString();
			result.Date = DateTime.Parse(tx["Date"].ToString());
			result.LastModifiedBy = tx["LastModifiedBy"].ToString();
			result.Subject = tx["Subject"].ToString();
			result.TransactionID = UInt32.Parse(tx["ID"].ToString());
			result.Type = tx["TransactionType"].ToString();

			ArrayList payeeList = new ArrayList();
			ArrayList consumerList= new ArrayList();

			// get the payee list
			DataRow[] drsPayee = tx.GetChildRows("relTransactionPayee");
			foreach (DataRow iDR in drsPayee)
			{
				UserAmountPair payee = new UserAmountPair();
				payee.username=iDR["UserID"].ToString();
				payee.amount=Decimal.Parse(iDR["Amount"].ToString());

				if (payee.username.Equals(currUserName))	// if the payee is the current user
				{ // find out the account used
					DataRow[] currAcc = accountTable.Select("ID = '"+iDR["AccountID"]+"'");
					foreach (DataRow iAccDR in currAcc)	// expect 1 or less
					{
						result.SourceExternalAccount= iAccDR["AccountName"].ToString();
					}
				}

				result.InvolvedPayees.Add(payee);
			}

			// get the consumer list
			DataRow[] drsConsumer = tx.GetChildRows("relTransactionConsumer");
			foreach (DataRow iDR in drsConsumer)
			{
				UserAmountPair consumer = new UserAmountPair();
				consumer.username=iDR["UserID"].ToString();
				consumer.amount=Decimal.Parse(iDR["Amount"].ToString());

				result.InvolvedConsumers.Add(consumer);
			}
			return result;
		}

		/// <summary>
		/// Checks if the user is currently logged in
		/// </summary>
		/// <param name="user"></param>
		/// <returns></returns>
		private bool isUserLogged(UserIdentity user)
		{
			return true;
		}

		public DateTime UserLastLoggedIn(UserIdentity user)
		{
			if (!isUserLogged(user)) new MizExceptions.UserNotLoggedInException();

			DateTime result=DateTime.Now; // in case not found
			
			DataRow[] usersRow;
			usersRow = userTable.Select("Name = '"+user.Name+"'");

			foreach (DataRow iDataRow in usersRow)
			{
				try
				{
					result= DateTime.Parse(iDataRow["LastLoggedIn"].ToString());
				} 
				catch (Exception e)	// if there was no last logged in time
				{
                    result = DateTime.Now;
				}

				break;
			}

			updateLoginTime(user.Name);	// This assumes that the last login time will be asked only once at every login. So just after retreiving the last login time, we update the login time.
			return result;


		}

		/// <summary>
		/// Updates the last logged in time to the current time
		/// </summary>
		/// <param name="username"></param>
		private void updateLoginTime(string username)
		{
			DataRow[] drsUser;
			drsUser = userTable.Select("Name = '"+username+"'");
			ArrayList result=new ArrayList();

			for (int i=0;i<drsUser.Length;i++)	// note: we expect only one result
			{
				// update the record
				DataRow newLoggedInTime = drsUser[i];
				newLoggedInTime["LastLoggedIn"]=DateTime.Now;
				drsUser[i]=newLoggedInTime;
			}
			
			updateXML();	  
		}

        /// <summary>
        /// Override InitializeLifetimeServices() and simply return null. 
        /// basically configured an MBR type that will never die as long as the hosting server
        /// application is alive and kicking.
        /// </summary>
        /// <returns></returns>
        public override object InitializeLifetimeService()
        {

            // Obtain the current lease info.
            ILease itfLeaseInfo =
            (ILease)base.InitializeLifetimeService();
            
            /*
            // Adjust settings.
            itfLeaseInfo.InitialLeaseTime = TimeSpan.FromMinutes(50);
            itfLeaseInfo.RenewOnCallTime = TimeSpan.FromMinutes(10);*/
            return null;
        }


	}
}
